home *** CD-ROM | disk | FTP | other *** search
- /* This file is part of 'minixfs' Copyright 1991,1992,1993 S.N.Henson */
-
- #include "minixfs.h"
- #include "proto.h"
- #include "global.h"
-
-
- /* search_dir serves 3 functions dependent on 'mode'
- 0 Search a directory for the entry 'name' if found return its inode number.
- 1 Create an entry 'name' return position of d_inum .
- 2 Delete an entry 'name' return inode num for success .
- 3 Find entry 'name', return position of d_inum.
- In all cases failure is denoted by a negative error number .
- */
-
- long search_dir(name,inum,drive,flag)
- const char *name;
- unsigned inum;
- int drive;
- int flag;
- {
- int entry,count;
- long zone; /* Zone number within dir */
- long lstfree; /* Last unused dir entry */
- d_inode rip;
- cache *tmp;
- int tflag;
- int incr;
- int mfname;
- static char tname[MNAME_MAX];
-
- incr=super_ptr[drive]->increment;
- mfname=MMAX_FNAME(incr);
-
- if( (tflag=do_trans(SRCH_TOS,drive)) )
- strcpy(tname,tosify(name,tflag,mfname));
-
- read_inode(inum,&rip,drive);
- /* Must be a directory ! */
- if(!IS_DIR(rip)) return EPTHNF;
-
- lstfree=-1l;
- for(zone=0; (count=cnext_zone(&rip,zone,&tmp,drive)>>L_DIR_SIZE);
- zone++)
- {
- dir_struct *try;
- for(entry=0,try=tmp->buffer->bdir;entry<count;entry+=incr,try+=incr) {
- unshort inumtemp;
- inumtemp=try->d_inum;
- if(inumtemp &&
- (!strncmp(name,try->d_name,mfname) || (tflag &&
- (!strcmp(tname,tosify(try->d_name,tflag,mfname)) ) )))
-
- {
- if(flag==KILL)
- {
- /* Never ever allow unlinking of '.' or '..' */
- if(zone==0 && entry<2)return EACCDN;
- try->d_inum=0;
-
- /* Next bit pinched from Minix,
- * store old inode num in last 2 bytes of name
- * This allows recovery in case of accident
- */
- *((unshort *)&try->d_name[MMAX_FNAME(incr)-2])=inumtemp;
-
- #if 1
- tmp->status=2;
- #else
- /* buffer tmp points to _might_ be invalidated in find_zone... */
- write_zone(find_zone(&rip,zone,drive,0),tmp
- ,drive,&syscache);
- #endif
- }
- if(flag==ADD) return EACCDN;
- if(flag==FIND || flag==KILL ) return inumtemp;
- if(flag==POS) return entry*DIR_ENTRY_SIZE+zone*BLOCK_SIZE;
- }
- if(flag==ADD && lstfree==-1l && !inumtemp)
- lstfree=zone*BLOCK_SIZE+entry*DIR_ENTRY_SIZE;
- }
- }
-
- if(flag==ADD) {
- dir_struct add[MAX_INCREMENT];
- strncpy(tname,name,mfname );
- tname[mfname]=0;
- if(badname(tname)) return EACCDN;
- if( do_trans(LWR_TOS,drive) ) Strlwr(tname);
- strncpy(add[0].d_name,tname,mfname);
- add[0].d_inum=0;
- if(l_write(inum,lstfree,(long)(mfname+2),add,drive)
- !=(mfname+2) ) return EACCDN;
- return( lstfree==-1l ? rip.i_size : lstfree);
- }
- return EFILNF;
- }
-
- /* Return '1' if 'name' has any illegal characters in it */
-
- int badname(name)
- char *name;
- {
- if(!*name)
- {
- DEBUG("Minixfs: Illegal null filename");
- return 1;
- }
- for(;*name;name++) if(BADCHR(*name))
- {
- DEBUG("minixfs: Bad character in filename");
- return 1;
- }
- return 0;
- }
-
- /* Return '1' if dir2 is a parent of dir1 , otherwise 0 or negative error
- * number
- */
-
- long is_parent(dir1,dir2,drive)
- unsigned dir1,dir2;
- int drive;
- {
- long itemp=dir1;
- for(;;)
- {
- if(itemp==dir2)
- {
- DEBUG("minixfs: invalid directory move");
- return 1;
- }
- if(itemp==ROOT_INODE)break;
- itemp=search_dir("..",itemp,drive,FIND);
- if(itemp < 0)
- {
- ALERT("Couldn't trace inode %d back to root",dir1);
- return EACCDN;
- }
- }
- return 0;
- }
-
-
-